<template>
  <div class="pptist-screen">
    <div class="slide-list" @wheel="$event => mousewheelListener($event)"
      @touchstart="$event => touchStartListener($event)" @touchend="$event => touchEndListener($event)"
      v-contextmenu="contextmenus" @click="execNext">
      <div :class="[
        'slide-item', 
        `turning-mode-${slide.turningMode || 'slideY'}`,
        {
          'current': index === slideIndex,
          'before': index < slideIndex,
          'after': index > slideIndex,
          'hide': (index === slideIndex - 1 || index === slideIndex + 1) && slide.turningMode !== currentSlide.turningMode,
        }
      ]" v-for="(slide, index) in slides" :key="slide.id">
        <div class="slide-content" :style="{
          width: slideWidth + 'px',
          height: slideHeight + 'px',
        }" v-if="Math.abs(slideIndex - index) < 2">
          <ScreenSlide :slide="slide" :scale="scale" :animationIndex="animationIndex" :turnSlideToId="turnSlideToId" />
        </div>
      </div>
    </div>

    <SlideThumbnails v-if="slideThumbnailModelVisible" :turnSlideToIndex="turnSlideToIndex"
      @close="slideThumbnailModelVisible = false" />
    <WritingBoardTool v-if="writingBoardToolVisible" @close="writingBoardToolVisible = false" />
    <div class="playbutton" :style="`color: ${theme.themeColor}`" @click="handleAutoplay" v-if="!autoplay && MultiPage">
      <IconPlay />
    </div>
    <div class="tools">
      <IconLeftTwo class="tool-btn" theme="two-tone" :fill="['#111', '#fff']" @click="execPrev()" />
      <IconRightTwo class="tool-btn" theme="two-tone" :fill="['#111', '#fff']" @click="execNext()" />
      <IconWrite class="tool-btn" theme="two-tone" v-if="route.query.type != 'vr'" :fill="['#111', '#fff']"
        @click="writingBoardToolVisible = true" />
    </div>

    <div class="page-number" @click="slideThumbnailModelVisible = true" v-if="showPageNumber">
      {{slideIndex + 1}} / {{slides.length}}
    </div>
    <div class="page-esc" @click="goback">
      <i class="close appIcon-iconfont appIcon-yulanguanbimoren "></i>
    </div>
    <div v-if="autoplay && MultiPage">
      <div class="page-esc page-pause" v-if='autoPlayTimer != 0' @click="closeAutoPlay">
        <IconPause />
      </div>
      <div class="page-esc page-pause" v-else @click="handleAutoplay">
        <IconPlayOne />
      </div>
    </div>
    <FullscreenSpin :loading="getoneing" tip="正在加载..." />
  </div>
</template>

<script lang="ts">
import { computed, defineComponent, onMounted, onUnmounted, provide, ref, watch } from 'vue'
import { throttle } from 'lodash'
import { storeToRefs } from 'pinia'
import { useSlidesStore, useMainStore, useScreenStore } from '@/store'
import { VIEWPORT_SIZE } from '@/configs/canvas'
import { KEYS } from '@/configs/hotkey'
import { ContextmenuItem } from '@/components/Contextmenu/types'
import { isFullscreen } from '@/utils/fullscreen'
import useScreening from '@/hooks/useScreening'
import { useRouter, useRoute } from 'vue-router'
import { editSpaceOffice , getOnePreview, getEditor} from "@/api/content"

import { message } from 'ant-design-vue'

import ScreenSlide from './ScreenSlide.vue'
import SlideThumbnails from './SlideThumbnails.vue'
import WritingBoardTool from './WritingBoardTool.vue'
import emitter, { EmitterEvents } from '@/utils/emitter'

export default defineComponent({
  name: 'screen',
  components: {
    ScreenSlide,
    SlideThumbnails,
    WritingBoardTool,
  },
  setup() {
    const mainStore = useMainStore()
    const { EditorType } = storeToRefs(mainStore)
    const slidesStore = useSlidesStore()
    const { slides, slideIndex, currentSlide, viewportRatio, theme } = storeToRefs(slidesStore)
    const { autoplay } = storeToRefs(useScreenStore())
    const route = useRoute()
    const router = useRouter()
    const slideWidth = ref(0)
    const slideHeight = ref(0)
    const MultiPage = ref(false); //是否为多页面
    watch(
      () => EditorType.value,
      (val: any) => {
        if(val == '2' || val == '3') { //自由编辑器和ppt显示多页面
          MultiPage.value = true
        }
      },
      {immediate: true}
    )
    const scale = computed(() => slideWidth.value / VIEWPORT_SIZE)

    const showPageNumber = ref(false)

    const slideThumbnailModelVisible = ref(false)

    const writingBoardToolVisible = ref(false)
   
    // 计算和更新幻灯片内容的尺寸（按比例自适应屏幕）
    const setSlideContentSize = () => {
      const winWidth = document.body.clientWidth
      const winHeight = document.body.clientHeight
      let width, height

      if (winHeight / winWidth === viewportRatio.value) {
        width = winWidth
        height = winHeight
      }
      else if (winHeight / winWidth > viewportRatio.value) {
        width = winWidth
        height = winWidth * viewportRatio.value
      }
      else {
        width = winHeight / viewportRatio.value
        height = winHeight
      }
      slideWidth.value = width
      slideHeight.value = height
    }

    // 窗口尺寸变化监听：窗口发生变化时更新幻灯片的大小
    // 如果退出了全屏，需要返回到编辑模式
    const { exitScreening } = useScreening()

    const windowResizeListener = () => {
      setSlideContentSize()
      if (!isFullscreen()) exitScreening()
    }

    onMounted(() => {
      setSlideContentSize()
      window.addEventListener('resize', windowResizeListener)
    })
    onUnmounted(() => {
      window.removeEventListener('resize', windowResizeListener)
    })

    // 当前页的元素动画列表和当前执行到的位置
    const animations = computed(() => currentSlide.value.animations || [])
    const animationIndex = ref(0)

    // 执行元素的入场动画
    const runAnimation = () => {
      const prefix = 'animate__'
      const animation: any = animations.value[animationIndex.value]
      animationIndex.value += 1

      const elRefs = document.querySelectorAll(`.groupid${animation.groupId}`)
      const animationName = `${prefix}${animation.type}`
      document.documentElement.style.setProperty('--animate-duration', `${animation.duration}ms`)
      document.documentElement.style.setProperty('--animate-delay', `${animation.delay}ms`)


      if (elRefs && animation.groupId) {
        for (let i = 0; i < elRefs.length; i++) {
          const el: any | null = elRefs[i].querySelector(`[class^=base-element-]`)
          el.classList.add(`${prefix}animated`, animationName)
          if(animation.infinite) {
            el.classList.add('animationinfinite')
          }
          const handleAnimationEnd = () => {
            document.documentElement.style.removeProperty('--animate-duration')
            document.documentElement.style.removeProperty('--animate-delay')

            el.classList.remove(`${prefix}animated`, animationName)
          }
          el.addEventListener('animationend', handleAnimationEnd, { once: true })
        }
      }
      else {
        const elRef = document.querySelector(`#screen-element-${animation.elId} [class^=base-element-]`)
        if (elRef) {
          elRef.classList.add(`${prefix}animated`, animationName)
          if(animation.infinite) {
            elRef.classList.add('animationinfinite')
          }

          const handleAnimationEnd = () => {
            document.documentElement.style.removeProperty('--animate-duration')
            document.documentElement.style.removeProperty('--animate-delay')

            elRef.classList.remove(`${prefix}animated`, animationName)

          }
          elRef.addEventListener('animationend', handleAnimationEnd, { once: true })
        }
      }
      
    }

    // 关闭自动播放
    const autoPlayTimer = ref(0)
    const closeAutoPlay = () => {
      if (autoPlayTimer.value) {
        clearInterval(autoPlayTimer.value)
        autoPlayTimer.value = 0
        // useScreenStore().setAutoplay(false)
      }
    }
    onUnmounted(closeAutoPlay)

    const throttleMassage = throttle(function(msg) {
      message.success(msg)
    }, 1000, { leading: true, trailing: false })

    // 向上/向下播放
    // 遇到元素动画时，优先执行动画播放，无动画则执行翻页
    // 向上播放遇到动画时，仅撤销到动画执行前的状态，不需要反向播放动画
    const execPrev = () => {
      if (animations.value.length && animationIndex.value > 0) {
        animationIndex.value -= 1
      }
      else if (slideIndex.value > 0) {
        slidesStore.updateSlideIndex(slideIndex.value - 1)
        const lastIndex = animations.value ? animations.value.length : 0
        animationIndex.value = lastIndex
      }
      else {
        throttleMassage('已经是第一页了')
      }
    }
    const execNext = () => {
      if (animations.value.length && animationIndex.value < animations.value.length) {
        runAnimation()
      }
      else if (slideIndex.value < slides.value.length - 1) {
        slidesStore.updateSlideIndex(slideIndex.value + 1)
        animationIndex.value = 0
      }
      else {
        throttleMassage('已经是最后一页了')
        closeAutoPlay()
      }
    }

    // 自动播放
    const autoPlay = () => {
      closeAutoPlay()
      message.success('开始自动放映')
      autoPlayTimer.value = setInterval(execNext, mainStore.switchTime)
    }
    const handleAutoplay = () => {
      closeAutoPlay()
      useScreenStore().setAutoplay(true)
      autoPlayTimer.value = setInterval(execNext, mainStore.switchTime)
    }
    
    // 鼠标滚动翻页
    const mousewheelListener = throttle(function(e: WheelEvent) {
      if (e.deltaY < -3) execPrev()
      else if (e.deltaY > 3) execNext()
    }, 1000, { leading: true, trailing: false })

    // 触摸屏上下滑动翻页
    const touchInfo = ref<{ x: number; y: number; } | null>(null)

    const touchStartListener = (e: TouchEvent) => {
      touchInfo.value = {
        x: e.changedTouches[0].pageX,
        y: e.changedTouches[0].pageY,
      }
    }
    const touchEndListener = (e: TouchEvent) => {
      if (!touchInfo.value) return

      const offsetX = Math.abs(touchInfo.value.x - e.changedTouches[0].pageX)
      const offsetY = e.changedTouches[0].pageY - touchInfo.value.y

      if ( Math.abs(offsetY) > offsetX && Math.abs(offsetY) > 50 ) {
        touchInfo.value = null
  
        if (offsetY > 0) execPrev()
        else execNext()
      }
    }
    // 快捷键退出放映
   
    // 快捷键翻页
    const keydownListener = (e: KeyboardEvent) => {
      const key = e.key.toUpperCase()
      if (key === KEYS.UP || key === KEYS.LEFT) execPrev()
      else if (
        key === KEYS.DOWN || 
        key === KEYS.RIGHT ||
        key === KEYS.SPACE || 
        key === KEYS.ENTER
      ) execNext()
      else if(key === KEYS.ESC) exitScreening()
    }
    const goback = () => {
      if(route.query.operate == '3') {
        if(route.query.fileType) {
          window.parent.postMessage(route.query.operate, "*");
        } else {
          router.go(-1);
        }
        return
      }
      if(route.query.screen == '1') {
        router.go(-1)
      } else {
        exitScreening()
      }
      
    }
    const getoneing = ref(false)
    
    const getInfo = () => {
      getoneing.value = true
      getEditor(route.query.appFileInfoId).then(res => {
        // console.log(9999999,res);
        if (res.code === 200) {
          if (res.data.content !== null) {
            const currentSlides = JSON.parse(JSON.stringify(res.data.content))
            console.log(res,'preview')
            slidesStore.setSlides(currentSlides)
            getoneing.value = false
            // let viewport = (res.data.officeHeight / res.data.data.officeWidth).toFixed(2) as unknown as number
            // viewport > 0 ? slidesStore.setViewportRatio(Number(viewport)) : slidesStore.setViewportRatio(1)
            // mainStore.$patch({
            //   canvasWidth: res.data.data.officeWidth,
            //   canvasHeight: res.data.data.officeHeight
            // })
            // setSlideContentSize()
          }
        }
      })
    }
    onMounted(() => {
      if(route.query.screen === '1') {
        getInfo()
      }
      if(useScreenStore().autoplay) {
        autoPlay()
      }
      document.addEventListener('keydown', keydownListener)
    })
    onUnmounted(() => {
      document.removeEventListener('keydown', keydownListener)
      useScreenStore().setAutoplay(false)
    })

    // 切换到上一张/上一张幻灯片（无视元素的入场动画）
    const turnPrevSlide = () => {
      slidesStore.updateSlideIndex(slideIndex.value - 1)
      animationIndex.value = 0
    }
    const turnNextSlide = () => {
      slidesStore.updateSlideIndex(slideIndex.value + 1)
      animationIndex.value = 0
    }

    // 切换幻灯片到指定的页面
    const turnSlideToIndex = (index: number) => {
      slideThumbnailModelVisible.value = false
      slidesStore.updateSlideIndex(index)
      animationIndex.value = 0
    }
    const turnSlideToId = (id: string) => {
      const index = slides.value.findIndex(slide => slide.id === id)
      if (index !== -1) {
        slidesStore.updateSlideIndex(index)
        animationIndex.value = 0
      }
    }

    const contextmenus = (): ContextmenuItem[] => {
      return [
        {
          text: '上一页',
          subText: '↑ ←',
          disable: slideIndex.value <= 0,
          handler: () => turnPrevSlide(),
        },
        {
          text: '下一页',
          subText: '↓ →',
          disable: slideIndex.value >= slides.value.length - 1,
          handler: () => turnNextSlide(),
        },
        {
          text: '第一页',
          disable: slideIndex.value === 0,
          handler: () => turnSlideToIndex(0),
        },
        {
          text: '最后一页',
          disable: slideIndex.value === slides.value.length - 1,
          handler: () => turnSlideToIndex(slides.value.length - 1),
        },
        { divider: true },
        {
          text: '显示页码',
          subText: showPageNumber.value ? '√' : '',
          handler: () => showPageNumber.value = !showPageNumber.value,
        },
        {
          text: '查看所有页面',
          handler: () => slideThumbnailModelVisible.value = true,
        },
        {
          text: '画笔',
          handler: () => writingBoardToolVisible.value = true,
        },
        { divider: true },
        {
          text: autoPlayTimer.value ? '取消自动放映' : '自动放映',
          handler: autoPlayTimer.value ? closeAutoPlay : autoPlay,
        },
        {
          text: '结束放映',
          subText: 'ESC',
          handler: exitScreening,
        },
      ]
    }
    
    provide('slideScale', scale)

    return {
      slides,
      slideIndex,
      currentSlide,
      slideWidth,
      slideHeight,
      scale,
      mousewheelListener,
      touchStartListener,
      touchEndListener,
      animationIndex,
      contextmenus,
      execPrev,
      execNext,
      slideThumbnailModelVisible,
      turnSlideToIndex,
      turnSlideToId,
      writingBoardToolVisible,
      showPageNumber,
      exitScreening,
      route,
      router,
      getInfo,
      goback,
      getoneing,
      theme,
      autoplay,
      handleAutoplay,
      closeAutoPlay,
      autoPlayTimer,
      MultiPage
    }
  },
})
</script>

<style lang="scss" scoped>
.playbutton {
  width: 80px;
  height: 80px;
  position: absolute;
  left: 50%;
  top: 50%;
  margin-left: -40px;
  margin-top: -40px;
  font-size: 80px;
  text-align: center;
  z-index: 99;
  line-height: 80px;
  cursor: pointer;
  border-radius: 50%;
}
.pptist-screen {
  width: 100%;
  height: 100%;
  position: relative;
  background-color: #111;
}
.slide-list {
  background: #1d1d1d;
  position: relative;
  width: 100%;
  height: 100%;
}
.slide-item {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;

  &.current {
    z-index: 2;
  }

  &.hide {
    opacity: 0;
  }

  &.turning-mode-no {
    &.before {
      transform: translateY(-100%);
    }
    &.after {
      transform: translateY(100%);
    }
  }
  &.turning-mode-fade {
    transition: opacity .75s;
    &.before {
      pointer-events: none;
      opacity: 0;
    }
    &.after {
      pointer-events: none;
      opacity: 0;
    }
  }
  &.turning-mode-slideX {
    transition: transform .35s;
    &.before {
      transform: translateX(-100%);
    }
    &.after {
      transform: translateX(100%);
    }
  }
  &.turning-mode-slideY {
    transition: transform .35s;
    &.before {
      transform: translateY(-100%);
    }
    &.after {
      transform: translateY(100%);
    }
  }
}
.slide-content {
  background-color: #fff;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  display: flex;
  justify-content: center;
  align-items: center;
}

.tools {
  position: fixed;
  bottom: 8px;
  left: 8px;
  font-size: 35px;
  color: #666;
  z-index: 10;
  cursor: pointer;
}
.tool-btn {
  opacity: .35;

  &:hover {
    opacity: .9;
  }
  & + .tool-btn {
    margin-left: 8px;
  }
}
.page-number {
  position: fixed;
  bottom: 8px;
  right: 8px;
  padding: 8px 12px;
  color: #666;
  background-color: #eee;
  border-radius: $borderRadius;
  z-index: 10;
  cursor: pointer;
}
.page-esc {
  position: fixed;
  top: 8px;
  right: 8px;
  width: 50px;
  height: 50px;
  text-align: center;
  line-height: 50px;
  border-radius: 50%;
  color: #666;
  background-color: #eee;
  z-index: 10;
  cursor: pointer;
  transition: .5s all ease;
  &:hover {
    background: #535252;
    color: #f1f1f1;
  }
}
.page-pause {
  top: initial;
  bottom: 70px;
}
</style>